﻿using System;
using System.IO;
using System.Configuration;
using System.Net;
using API.WindowsLive.SkyDrive.UserInterface;
using API.WindowsLive.SkyDrive.BusinessLogic;
using API.WindowsLive.SkyDrive.Events;
using System.Threading;
using System.Collections.Generic;
using HgCo.WindowsLive.SkyDrive;

namespace API.WindowsLive.SkyDrive
{
    public class SkyDriveSynchronizerStarter
    {

        String startFolder, destinationFolder, userName, password, startSchedule, endSchedule;
        Boolean proxyOn, deleteLocalFiles, deleteRemoteFiles, download, upload, estimateTime, error, updateLocalFiles, updateRemoteFiles, scheduleOn, loopSchedule;
        WebProxy webProxy = null;
        SkyDriveLogic skyDriveLogic = null;
        Scheduler sched = null;

        IMainUI userInterface = null;
        int waitingTime;
        long fileSize;

        static void Main(string[] args)
        {
            SkyDriveSynchronizerStarter starter = new SkyDriveSynchronizerStarter();
            starter.start();

            Console.WriteLine("Done press any key to continue");
            Console.ReadLine();
        }

        public SkyDriveSynchronizerStarter()
        {
        }

        public void start()
        {
            Console.WriteLine("Load configuration");
            loadVariables();

            Console.WriteLine("Load UI");
            loadInterface();

            Console.WriteLine("Initializing");
            loadObject();

            ThreadStart threadStart = new ThreadStart(this.runSkyDrive);
            Thread thread = new Thread(threadStart);
            sched = new Scheduler(startSchedule, endSchedule, thread, scheduleOn, loopSchedule);

            attachHandlers();

            sched.launchSchedule();
        }

        public void runSkyDrive()
        {
            Console.WriteLine("Log in");
            login();

            if (!error)
            {
                Console.WriteLine("Warming up");
                skyDriveLogic.WarmUp();

                startTransfer();
            }
        }


        public static Dictionary<String, String> GetUserNameAndPassword()
        {
            Dictionary<String, String> dico = new Dictionary<String, String>();

            dico.Add("username", "");
            dico.Add("password", @"");

            return dico;
        }

        private void loadVariables()
        {
            Dictionary<String, String> dico = GetUserNameAndPassword();

            startFolder = ConfigurationManager.AppSettings["StartFolder"].ToString();
            destinationFolder = ConfigurationManager.AppSettings["DestinationWebFolder"].ToString();
            waitingTime = Int32.Parse(ConfigurationManager.AppSettings["TimeOut"].ToString());
            userName = dico["username"];
            password = dico["password"];
            proxyOn = Boolean.Parse(ConfigurationManager.AppSettings["ProxyOn"].ToString());
            deleteLocalFiles = Boolean.Parse(ConfigurationManager.AppSettings["DeleteLocalFiles"].ToString());
            deleteRemoteFiles = Boolean.Parse(ConfigurationManager.AppSettings["DeleteRemoteFiles"].ToString());
            download = Boolean.Parse(ConfigurationManager.AppSettings["Download"].ToString());
            upload = Boolean.Parse(ConfigurationManager.AppSettings["Upload"].ToString());
            estimateTime = Boolean.Parse(ConfigurationManager.AppSettings["EstimateTime"].ToString());
            fileSize = Int64.Parse(ConfigurationManager.AppSettings["MaxFileSize"].ToString());
            updateLocalFiles = Boolean.Parse(ConfigurationManager.AppSettings["UpdateLocalFiles"].ToString());
            updateRemoteFiles = Boolean.Parse(ConfigurationManager.AppSettings["UpdateRemoteFiles"].ToString());

            scheduleOn = Boolean.Parse(ConfigurationManager.AppSettings["ScheduleOn"].ToString());
            loopSchedule = Boolean.Parse(ConfigurationManager.AppSettings["LoopSchedule"].ToString());
            startSchedule = ConfigurationManager.AppSettings["StartTime"].ToString();
            endSchedule = ConfigurationManager.AppSettings["EndTime"].ToString();
        }

        private void loadInterface()
        {
            userInterface = new CommandLineInterface();
        }

        private void login()
        {
            try
            {
                skyDriveLogic.login();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                error = true;
            }
        }

        private void loadObject()
        {
            try
            {
                if (proxyOn)
                {
                    String proxyHost = ConfigurationManager.AppSettings["ProxyHost"].ToString();
                    int proxyPort = Int32.Parse(ConfigurationManager.AppSettings["ProxyPort"].ToString());
                    webProxy = new WebProxy(proxyHost, proxyPort);
                }

                skyDriveLogic = new SkyDriveLogic(userName, password, waitingTime, fileSize, new DirectoryInfo(startFolder), destinationFolder, webProxy);

                skyDriveLogic.UpdateLocalFiles = updateLocalFiles;
                skyDriveLogic.UpdateRemoteFiles = updateRemoteFiles;

            }
            catch (Exception ex)
            {
                //Console.WriteLine("An exception occured while trying to instantiate SkyDrive, check that your username and password are correct\n" + ex.Message);
                error = true;
            }
        }

        private void startTransfer()
        {
            if (upload)
            {
                if (estimateTime)
                {
                    Console.WriteLine("Estimate upload");
                    skyDriveLogic.checkFilesInWebDirectory();

                    /*Console.WriteLine("Total number of files to copy is " + filesToUpload.Count);
                    foreach (FileInfo fileInfo in filesToUpload)
                    {
                        Console.WriteLine(fileInfo.FullName);
                    }*/
                }
                Console.WriteLine("Start upload");
                skyDriveLogic.Upload();
            }

            if (deleteRemoteFiles)
            {
                Console.WriteLine("Delete web files");
                skyDriveLogic.deleteWebFilesIfNotInLocal();
            }

            if (download)
            {
                if (estimateTime)
                {
                    Console.WriteLine("Estimate download");
                    skyDriveLogic.checkFilesInLocalDirectory();

                    /*Console.WriteLine("Total number of files to download is " + filesToDownload.Count);
                   foreach (WebFileInfo webFileInfo in filesToDownload)
                   {
                       Console.WriteLine(webFileInfo.PathUrl);
                   }*/
                }
                Console.WriteLine("Start download");
                skyDriveLogic.Download();
            }

            if (deleteLocalFiles)
            {
                Console.WriteLine("Delete local files");
                skyDriveLogic.deleteLocalFilesIfNotInWeb();
            }

        }

        private void attachHandlers()
        {
            SkyDriveLogic.FileChangedHandler fileChangedHandler = new SkyDriveLogic.FileChangedHandler(userInterface.FileChanged);
            skyDriveLogic.FileChanged += fileChangedHandler;

            SkyDriveLogic.ExceptionHandler exceptionRaisedHandler = new SkyDriveLogic.ExceptionHandler(userInterface.ExceptionRaised);
            skyDriveLogic.ExceptionRaised += exceptionRaisedHandler;

            Scheduler.StartHandler startRaisedHandler = new Scheduler.StartHandler(userInterface.ScheduleStarted);
            sched.RaiseStart += startRaisedHandler;

            Scheduler.EndHandler endRaisedHandler = new Scheduler.EndHandler(userInterface.ScheduleEnded);
            sched.RaiseEnd += endRaisedHandler;

            Scheduler.WaitHandler waitRaisedHandler = new Scheduler.WaitHandler(userInterface.ScheduleWaiting);
            sched.RaiseWait += waitRaisedHandler;
        }

    }
}
